# -*- coding: utf-8 -*-
import mod.server.extraServerApi as serverApi
import lobbyGame.netgameApi as lobbyGameApi
from mod.server.system.serverSystem import ServerSystem

from dwjjCoreServerScripts.common import logger


class RuleModule(object):

    def __init__(self, serverSystem, config):
        # type: (ServerSystem, dict) -> None
        self.serverSystem = serverSystem
        self.config = config
        # 判断该系统是否启用
        if not config["enable"]:
            self.enable = False
            return
        # 初始化引擎工厂
        self.InitComp()
        # 初始化基础参数
        self.InitSetting()
        # 注册监听器
        self.InitListener()

    def InitComp(self):
        self.gameComp = serverApi.GetEngineCompFactory().CreateGame(serverApi.GetLevelId())
        self.blockInfoComp = serverApi.GetEngineCompFactory().CreateBlockInfo(serverApi.GetLevelId())

    def InitSetting(self):
        # 城市保护
        if self.config["openCityProtect"]:
            self.gameComp.OpenCityProtect()
        # 禁止所有容器界面的打开
        if self.config["disableContainers"]:
            self.gameComp.SetDisableContainers(True)

        # 设置龙蛋禁止传送区域
        dragonEggLimitAreaDict = self.config["dragonEggLimitArea"]
        if dragonEggLimitAreaDict["enable"]:
            for k, area in dragonEggLimitAreaDict["areas"].items():
                lobbyGameApi.SetForbidDragonEggTeleportField(
                    area["fid"],
                    area["dim"],
                    (area["minX"], area["minY"], area["minZ"]),
                    (area["maxX"], area["maxY"], area["maxZ"]),
                    area["priority"],
                    area["isForbid"]
                )

        # 设置是否禁用藤曼蔓延生长
        if self.config["disableVineBlockSpread"]:
            self.gameComp.DisableVineBlockSpread(True)
        # 禁止/允许地图中的流体流动
        if self.config["forbidLiquidFlow"]:
            self.gameComp.ForbidLiquidFlow(True)
        # 闪电是否允许点燃实体
        if self.config["lightningIgniteEntity"]:
            self.gameComp.SetCanActorSetOnFireByLightning(False)
        # 闪电是否允许点燃方块
        if self.config["lightningIgniteBlock"]:
            self.gameComp.SetCanBlockSetOnFireByLightning(False)

        # 禁止丢弃物品
        if self.config["disableDropItem"]:
            self.gameComp.SetDisableDropItem(True)
        # 屏蔽饥饿度
        if self.config["disableHunger"]:
            self.gameComp.SetDisableHunger(True)

        # 伤害CD
        if self.config["hurtCD"] > 0:
            self.gameComp.SetHurtCD(self.config["hurtCD"])

        # 游戏规则
        configGameRuleDict = self.config["gameRule"]
        if configGameRuleDict["enable"]:
            gameRuleDict = dict()
            if "option_info" in configGameRuleDict:
                gameRuleDict["option_info"] = configGameRuleDict["option_info"]
            if "cheat_info" in configGameRuleDict:
                gameRuleDict["cheat_info"] = configGameRuleDict["cheat_info"]
            self.gameComp.SetGameRulesInfoServer(gameRuleDict)

    def InitListener(self):
        # 是否禁止爆炸破坏方块
        if self.config["explosionBlock"]:
            self.explosionIgniteTNT = self.config["explosionIgniteTNT"]
            self.serverSystem.ListenForEvent(serverApi.GetEngineNamespace(), serverApi.GetEngineSystemName(),
                                             "ExplosionServerEvent", self, self.OnExplosion, 0)
        # 是否禁用实体被传送门传送
        if self.config["entityPortal"]:
            self.serverSystem.ListenForEvent(serverApi.GetEngineNamespace(), serverApi.GetEngineSystemName(),
                                             "WillTeleportToServerEvent", self, self.OnEntityPortal, 0)

        # 生物对方块进行操作
        self.griefingBlock = self.config["griefingBlock"]
        if self.griefingBlock["enable"]:
            self.serverSystem.ListenForEvent(serverApi.GetEngineNamespace(), serverApi.GetEngineSystemName(),
                                             "MobGriefingBlockServerEvent", self, self.OnMobGriefingBlock, 0)

        # 盔甲架被点燃
        if self.config["armorFire"]:
            self.serverSystem.ListenForEvent(serverApi.GetEngineNamespace(), serverApi.GetEngineSystemName(),
                                             "OnFireHurtEvent", self, self.OnArmorFire, 0)

    def OnExplosion(self, e):
        dim = e["dimensionId"]
        for pos in e["blocks"]:
            blockDict = self.blockInfoComp.GetBlockNew((pos[0], pos[1], pos[2]), dim)
            if blockDict["name"] == "minecraft:tnt":
                # 判断是否点燃tnt
                if not self.explosionIgniteTNT:
                    pos[3] = True
            else:
                pos[3] = True

    def OnEntityPortal(self, e):
        if e["cause"] == serverApi.GetMinecraftEnum().EntityTeleportCause.GateWay:
            entityId = e["entityId"]
            comp = serverApi.GetEngineCompFactory().CreateEngineType(entityId)
            entityType = comp.GetEngineType()
            entityTypeEnum = serverApi.GetMinecraftEnum().EntityType

            if not (entityType & entityTypeEnum.Player == entityTypeEnum.Player):
                e["cancel"] = True

    def OnMobGriefingBlock(self, e):
        blockName = e["blockName"]
        entityId = e["entityId"]
        comp = serverApi.GetEngineCompFactory().CreateEngineType(entityId)
        entityType = comp.GetEngineType()
        entityTypeEnum = serverApi.GetMinecraftEnum().EntityType

        # 农田/耕地 破坏保护
        if blockName == "minecraft:farmland":
            if entityType & entityTypeEnum.Player == entityTypeEnum.Player:
                if self.griefingBlock["farmlandPlayer"]:
                    e["cancel"] = True
            if entityType & entityTypeEnum.VillagerBase == entityTypeEnum.VillagerBase:
                if self.griefingBlock["farmlandVillager"]:
                    e["cancel"] = True
            else:
                if self.griefingBlock["farmlandOtherEntity"]:
                    e["cancel"] = True

        else:
            if self.griefingBlock["other"]:
                e["cancel"] = True
                if self.griefingBlock["otherDebugMsg"]:
                    logger.Debug("[GriefingBlock]" + str(e) + ", entityType: " + comp.GetEngineTypeStr())

    def OnArmorFire(self, e):
        entityId = e["victim"]
        entityComp = serverApi.GetEngineCompFactory().CreateEngineType(entityId)
        entityType = entityComp.GetEngineType()
        entityTypeEnum = serverApi.GetMinecraftEnum().EntityType

        if entityType & entityTypeEnum.ArmorStand == entityTypeEnum.ArmorStand:
            e["cancel"] = True



